#pragma once
#include "sock.hpp"
#include "log.hpp"
#include <pthread.h>

#include <functional>
#include <iostream>
#include <string>

static const uint16_t defaultport = 8888;

using func_t = function<string(string &)>;

class httpServer;

class threadData{
public:
    threadData(int sock,const string &ip,const uint16_t &port, httpServer *tsvrp): _sock(sock), _ip(ip), _port(port), _tsvrp(tsvrp) {

    }
    ~threadData(){
        
    }


public:
    int _sock;
    string _ip;
    uint16_t _port;
    httpServer *_tsvrp;
};

class httpServer{
public:
    httpServer(func_t f,int port = defaultport):func(f), _port(port){

    }

    void InitServer(){
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
    }

    void handlerHttpRequest(int sock){
        //从套接字中读
        char buf[4096];
        string request;
        ssize_t s = recv(sock, buf, sizeof(buf) - 1, 0); // 我们认为一次就能够读完
        if(s>0){
            buf[s] = 0;
            request = buf;
            //根据请求做出响应
            string response = func(request);
            send(sock, response.c_str(), response.size(), 0);
        }
        else{
            logMessage(INFO, "client quit!");
        }
    }

    static void *threadRoutine(void *args){
        pthread_detach(pthread_self());
        threadData *td = static_cast<threadData *>(args);
        ////使用当前对象的 func 成员变量来生成响应，没有用到using func_t = function<string(const string &)>;
        //如果想要改变功能，就需要更改函数指针的指向，不符合多态
        // heandlerHttpRequest(td->_sock); 

        //用threadData托管该对象，只需要传入符合格式的函数就能调用
        td->_tsvrp->handlerHttpRequest(td->_sock);
        close(td->_sock);

        delete td;
        return nullptr;
    }

    void Start(){
        for (;;){
            string clientip;
            uint16_t clientport;
            
            int sock = _listensock.Accept(&clientip, &clientport);
            if(sock<0){
                continue;
            }

            pthread_t tid;
            threadData *td = new threadData(sock, clientip, clientport, this);
            pthread_create(&tid, nullptr, threadRoutine, td);
        }
    }



    ~httpServer(){

    }

private:
    int _port;
    Sock _listensock;
    func_t func;
};